#pragma once

#include <core/strings/BaseString.h>
#include <core/sync/lock.h>

#include <map>
#include <mutex>
#include <string>

#include "BondInfo.h"
#include "bondlib.h"
#include "qbprotocol/include/SSFilters.h"

/*
[内存优化][scofined.qi]
REPORT加入到容器的时候,压缩编码成ReportEncoder::FieldArray对象
此对象内存后面紧接着实际的内容编码,FieldArray只是对象头部

普通访问模式下,FieldArray需要先转化成REPORT对象
快速模式下,如GetModifyTime,可以通过字段索引来直接访问REPORT的
某个成员,而不需要先转化成REPORT对象

优化措施:
        1.使用KeyString取代std::string
        2.使用vector取代原先的std::map
        3.使用编码后的FieldArray取代REPORT(压缩率是29%)
*/
using namespace std;
enum class
    kReportField {  // 表示结构体report_t中每个字段的对应的序号,必须严格一一对应
      Version = 0,
      Market,
      BondKey,
      ListedMarket,
      Time,
      CreateTime,
      DealStatus,
      CompanyId,
      PriceStatus,

      // 对应price_t的字段顺序
      Bid_id,
      Bid_deal_status,
      Bid_flag_bargain,
      Bid_flag_relation,
      Bid_flag_vip,
      Bid_company_id,
      Bid_flag_bad,
      Bid_price_status,
      Bid_rebate,
      Bid_return_point,
      Bid_clean_price,
      Bid_full_price,
      Bid_yield_price,
      Bid_sPrice,
      Bid_quotetype,
      Bid_sVolume,
      Bid_description,
      Bid_interpret,
      Bid_exercise,
      Bid_create_time,
      Bid_time,

      // 对应price_t的字段顺序
      Ask_id,
      Ask_deal_status,
      Ask_flag_bargain,
      Ask_flag_relation,
      Ask_flag_vip,
      Ask_company_id,
      Ask_flag_bad,
      Ask_price_status,
      Ask_rebate,
      Ask_return_point,
      Ask_clean_price,
      Ask_full_price,
      Ask_yield_price,
      Ask_sPrice,
      Ask_quotetype,
      Ask_sVolume,
      Ask_description,
      Ask_interpret,
      Ask_exercise,
      Ask_create_time,
      Ask_time,

      // 对应indx_price_t的字段顺序
      Idx_symbol,
      Idx_price,
      Idx_clean_price,
      Idx_company_id,
      Idx_modify_time,

      PriceSel,
      TradePrice,
      PkgId,
      Count
    };

class S_BONDLIB_EXPORT CCompanyRepMap {
 public:
  typedef std::map<std::string, REPORT> ReportMap;
  ReportMap m_map;  //<brokerID,REPORT>
};
template <typename CONTAINER>
class MapWrapper {
  typedef std::map<std::string, REPORT> ReportMap;
  typedef typename CONTAINER::key_type key_type;
  // typedef  typename  CONTAINER::value_type value_type;
  typedef typename CONTAINER::mapped_type mapped_type;
  typedef typename CONTAINER::iterator iterator;
  typedef typename CONTAINER::const_iterator const_iterator;
  CONTAINER& m_container;

 public:
  MapWrapper(CONTAINER& cont) : m_container(cont) {}
  iterator begin() { return m_container.begin(); }
  iterator end() { return m_container.end(); }
  iterator find(const key_type& key) { return m_container.find(key); }
  int size() const { return m_container.size(); }
  int bytes() const { return 0; }
  void clear() { m_container.clear(); }
  void emplace(const key_type& key, const mapped_type& rpt) {
    m_container.emplace(key, rpt);
  }
  iterator erase(const_iterator _Where) { return m_container.erase(_Where); }
};

typedef qb::base::KeyString KeyString;
class ZippedReportMap;
class S_BONDLIB_EXPORT CBondCompanyRep {
  typedef CCompanyRepMap::ReportMap ReportMap;
  typedef MapWrapper<ReportMap> ReportMapWrapper;

 public:
  class S_BONDLIB_EXPORT ApplyCallback {
   public:
    virtual bool DoAccess(const REPORT& quote) {
      return false;
    }  // true表示可继续,false表示中断
    virtual bool DoModify(REPORT& quote) {
      return false;
    }  // true表示可继续,false表示中断
  };
  CBondCompanyRep();
  virtual ~CBondCompanyRep();
  bool Clear();
  bool ClearLiquidation(int clrFlag);

  int GetSize();
  int GetBytes(int mode = 0);
  int GetItemSize() const { return sizeof(XCQUOTE); }
  const char* GetName() const;

  bool InsertCompanyRep(const REPORT& newElement);
  bool GetCompanyRepByKey(const std::string& sKey, REPORT& stRep);

  void ApplyAccess(bool all, const std::string& sKey, ApplyCallback* callback);
  void ApplyModify(bool all, const std::string& sKey, ApplyCallback* callback);

  //-------------------------------------------------------------------------
  // Summary:
  // 		根据key值得到报价信息，若sKey为空（全部时），则取所有Broker报价中的最新的报价
  // Parameters:
  // 		sKey - BrokerID
  // 		stRep - 报价
  // Returns:
  // 		若成功返回true,否则返回false
  //-------------------------------------------------------------------------
  bool GetReport(const std::string& sKey, REPORT& stRep,
                 int nFlag);  // flag = 0 取最新，1 取最新有效，2 取最新双边

  // 由CBondContainer::GetLatestCompanyRepByBondIndex改造而来
  bool GetLatestReport(REPORT& stRep, bool bBuyPool);

  bool TestBidPrice(const BLHCONDITION& Cond);
  bool TestOfrPrice(const BLHCONDITION& Cond);
  bool TestBidOfrPrice(const BLHCONDITION& Cond);

  static bool IsBidPriceValid(const REPORT& stRep);
  static bool IsOfrPriceValid(const REPORT& stRep);

 public:  // 高性能接口
  time_t GetModifyTime(const std::string& szKey);
  double GetBuyNetPrice(const std::string& szKey);
  double GetBuyPrice(const std::string& key);
  double GetSellPrice(const std::string& key);
  double GetSellNetPrice(const std::string& key);
  const void* GetReportField(const char* key, int index);
  bool IsHasPrice(const char* szKey, int flag = 0);

 protected:
  ZippedReportMap* m_zip;
  // CCompanyRepMap			m_RepMap;
  qb::base::Spinlock m_lock;  // TODO spin?
};
